package it.unibo.convoycruisecontrol.boatsubsystem.test.unit;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import it.unibo.convoycruisecontrol.boatsubsystem.IDashboard;
import it.unibo.location.ILocation;

import org.junit.Before;
import org.junit.Test;

public abstract class DashboardTestCase 
{
	public abstract IDashboard createConcreteDashboar();
	protected IDashboard dashboard;
	
	@Before
	public void beforeTest()
	{
		dashboard = createConcreteDashboar();
	}

	@Test
	public void invariant()
	{
		float distance = 3.0f;
		dashboard.updateDistanceCovered(distance);
		assertEquals(distance, dashboard.getDisplayedDistanceCovered(), 0);
		distance = 5.78f;
		dashboard.updateDistanceCovered(distance);
		assertEquals(distance, dashboard.getDisplayedDistanceCovered(), 0);

		float speed = 5.0f;
		dashboard.updateCurrentSpeed(speed);
		assertEquals(speed, dashboard.getDisplayedCurrentSpeed(), 0);
		speed = 356.72f;
		dashboard.updateCurrentSpeed(speed);
		assertEquals(speed, dashboard.getDisplayedCurrentSpeed(), 0);

		List<ILocation> locations = new ArrayList<ILocation>();
		locations.add(new MockLocation(34.6, 23.899, 98));
		locations.add(new MockLocation(62.8, 34.56, 0));
		locations.add(new MockLocation(23.6, 26.12, 35.7));
		dashboard.updateMap(locations);
		assertEquals(locations, dashboard.getDisplayedLocations());
		locations.add(new MockLocation(34.89, 2.399, 2.67));
		locations.add(new MockLocation(12.85, 8.96, 0.67));
		locations.add(new MockLocation(76.83, 68.23, 98.56));
		dashboard.updateMap(locations);
		assertEquals(locations, dashboard.getDisplayedLocations());
	}

	// Mock object: solo per il testing
	private class MockLocation implements ILocation
	{
		private double latitude;
		private double longitude;
		private double altitude;
		private float accuracy;
		private long sampleTime;

		public MockLocation(double latitude, double longitude, double altitude){
			this.latitude = latitude;
			this.longitude = longitude;
			this.altitude = altitude;
			this.accuracy = (float) 0.1;
			Date now = new Date();
			this.sampleTime = now.getTime();
		}

		@Override
		public double getLatitude() {
			return latitude;
		}

		@Override
		public double getLongitude() {
			return longitude;
		}

		@Override
		public double getAltitude() {
			return altitude;
		}

		@Override
		public float distanceTo(ILocation location) {
			return 0;
		}

		@Override
		public float getAccuracy() {
			return accuracy;
		}

		@Override
		public long getSampleTime() {
			return sampleTime;
		}

		@Override
		public String toString() 
		{
			return "Lat: " + latitude + " Long: " + longitude + " Alt: " + altitude;
		}

		@Override
		public boolean equals(Object obj) 
		{
			if(obj == this)
				return true;

			if(obj == null || !(obj instanceof ILocation))
				return false;

			ILocation loc = (ILocation)obj;

			return (loc.getLatitude() == this.getLatitude()) &&
					(loc.getLongitude() == this.getLongitude()) &&
					(loc.getAltitude() == this.getAltitude());
		}

	}
}
